#include"../include/lib_headers.h"

void mount_hashTable()
{	

	int i; fd file;
	
/*	printf("fd_list paths are : \n");
	for(i=0;i<h->usedFds;i++)
		printf("\n%s",array[i].fileName);
*/	
	
	/* Defining the size of hash table */


	
 	hashtable = (h_node*)malloc(HASHSIZE * sizeof(h_node));
	htable_init(hashtable); /* initializing the hash table*/

	for(i=0;i< h->usedFds;i++){
		file = array[i];
//ORIGINAL	
		htable_insert(hashtable,file);
	}
}


void unmount_hashTable(h_node *hashtable)
{
    int i = 0;
    h_node *target,*temp;
    if(hashtable == NULL)return;
    else
    {

         for(i = 0; i < HASHSIZE; i++)
        {   
              if(strcmp(hashtable[i].file.fileName,"") !=0)
            {
                   target = hashtable + i;
                target = target->next;  //go to the 1st node of linked list..
                   while(target!=NULL)
                {
                        temp=target;
                        target = target->next;
                    free(temp);
                }
              }
         }
        free(hashtable);
    }

}




/* fire up hashtable */

void htable_init(h_node *hashtable) {
 	int i = 0;

 	for(i = 0; i < HASHSIZE; i++){
		strcpy(hashtable[i].file.fileName,"");
		strcpy(hashtable[i].file.fullPath,"");
		strcpy(hashtable[i].file.fileType,"");
		hashtable[i].next=NULL;		
	}
}

/* insert fname into hashtable */

void htable_insert(h_node *hashtable,fd file) {
	
 	int index = 0;
 	index = htable_hash(file.fileName);  /* determine index from hash function */

 	if(!(strcmp(hashtable[index].file.fileName,"")==0)) {
  		
  		htable_resolve(hashtable, index, file);	/* collision occurs - resolve by chaining */
  
  
 	} 
	else {
		strcpy(hashtable[index].file.fileName,file.fileName); /* Storing filename into hashtable */
  		strcpy(hashtable[index].file.fileType,file.fileType); /* Storing file type into hashtable */
		strcpy(hashtable[index].file.fullPath,file.fullPath); /* Storing file path into hashtable */
		//hashtable[index].file.blockno = file.blockno;/* Storing block no in which data of file is stored, into hashtable */
 	}
}

/* Hash function to hash file name into hashtable
 * Assuming file name to start with either "0 to 9" or "A to Z " or "a to z" or "_"
 */
 int htable_hash(char *strFileName) {
	 int index = 0;
	 char firstLetter = strFileName[0];    /* extracting the first character from the filename */
 
	if(firstLetter >=32 && firstLetter <= 46)
		index = firstLetter - 32;
	else if(firstLetter >=48 && firstLetter <= 126)
	 	index = firstLetter - 33;
	return index;
}
	
/* resolve collisions in hashtable using chaining*/
void htable_resolve(h_node *hashtable,int loc,fd file1) {

 	h_node *tmp, *new;

 	/* reach the index where chaining has to be done */
 	tmp = hashtable + loc;

  	/* defining new element */
  	new = (h_node *)malloc(sizeof(h_node));
  	strcpy(new->file.fileName, file1.fileName);
  	strcpy(new->file.fullPath, file1.fullPath);
  	strcpy(new->file.fileType," ");
 
  	/* inserting new element at the head */
  	new->next=tmp->next;
 	tmp->next = new;
}

/* display hashtable */
void htable_display(h_node *hashtable) {
 int i = 0, count=0;
 h_node *target;
 printf("\n");

 for(i = 0; i < HASHSIZE; i++) {
  if(strcmp(hashtable[i].file.fileName,"") !=0) {
   target = hashtable + i;
   while(target){
     printf("Filename: %40s\t\t\tFull Path: %40s\n", target->file.fileName, target->file.fullPath);
     count++;
     target = target->next;
     }
  } 
 }
  printf("count = %d\n\n", count); 
}


/* delete an entry from hashtable
 * input: file descriptor
 */

void htable_delete(h_node *hashtable,fd file1) {
	h_node *start;
	h_node *temp;
	int index = 0;
	/* get the index from the hash function*/
	index = htable_hash(file1.fileName);
	
	/* no item at this location */
	if(hashtable[index].file.fileName == NULL)
		return ;
	
	/* only one item at this location */
	if(hashtable[index].next == NULL)
	{ 
	        if(strcmp(hashtable[index].file.fullPath, file1.fullPath) == 0)
	        {
	                /* item found */
	                strcpy(hashtable[index].file.fileName,"");
	                strcpy(hashtable[index].file.fullPath,"");
	        }
	}
 
	/* there is a chaining case */
	else
	{
	        start = hashtable + index;
	        /*checking if it's the head element*/
	        if(strcmp(start->file.fullPath, file1.fullPath)==0)
	        {
	                temp=start->next;
	                strcpy(start->file.fullPath,temp->file.fullPath);
	                strcpy(start->file.fileName,temp->file.fileName);
	                if(temp->next != NULL)
	                        start->next = temp->next;
	                else
	                        start->next = NULL;
	        /* free the node which was connected to the head */
	        free(temp);
	        }

	        /*checking if element is in the chain*/
	        else
	        {
	                /* go till the end of the chain */
	                while(start->next != NULL)
	                {	//break;
	                	/* if a match is found*/
	                        if(start->next != NULL && strcmp(start->next->file.fullPath, file1.fullPath) == 0)
	                         {	
	                        
	                                temp = start->next;
	                                if(start->next->next != NULL)
	                                        start->next = start->next->next;
	                                else
	                                        start->next = NULL;
	                                /* free the h_node which has to be deleted */
	                                free(temp);
	                                
	                        }
	                        if(start->next!=NULL){
	                        	start=start->next;
	                        }	
	                        else
	                        	break;      	
	                        
	                }
	                		

	        }
	}
	return ;	
}
/* Search file with filename as input and print the file name and corresponding path, if file is present */

char* htable_search(h_node *hashtable,char *strFileName,char *opFileName){
	
 	int index = 0,count =0;
	char *fileName=NULL,*tempstr = NULL;
 	index = htable_hash(strFileName);	/* determine index from hash function */
	
	tempstr = strrchr( strFileName, '.' );
	if(tempstr!=NULL)
	{
		fileName = strtok( strFileName, tempstr );
		if(fileName==NULL)
			fileName=strFileName;
	}
	else
		fileName=strFileName;
	
	FILE *fp;

  	if((fp=fopen(opFileName, "wb"))==NULL)
	{ 
    		sprintf(outputStr,"%s %s","searchfile_FAILURE",ERR_VFS_SEARCHFILE_00);
		return outputStr;
	}
	
	fprintf(fp,"\n"); 

	/* if file name at the index of hashtable is null, then file is not present in hash table and return */	
	if(hashtable[index].file.fileName == NULL){  
	 	FILE *fp = fopen(opFileName, "wb");
		fwrite("", 0, 1, fp);
		fclose(fp);
		sprintf(outputStr,"%s %s","searchfile_SUCCESS","0");
		return outputStr;	
	}
	
	if(strncmp(fileName,hashtable[index].file.fileName,strlen(fileName))==0){
		++count;
		fprintf(fp,"FILE NAME : ");
		fwrite(hashtable[index].file.fileName,strlen(hashtable[index].file.fileName),1,fp);
		fprintf(fp,"\n");
		fprintf(fp,"FILE PATH : ");
		fwrite(hashtable[index].file.fullPath,strlen(hashtable[index].file.fullPath),1,fp);
		fprintf(fp,"\n\n\n\n");
	}

	h_node *tmp;
	tmp = hashtable + index;
	while(tmp->next != NULL){
		tmp = tmp->next;
		if(strncmp(fileName,tmp->file.fileName,strlen(fileName))==0){
				++count;
				fprintf(fp,"FILE NAME : ");
				fwrite(tmp->file.fileName,strlen(tmp->file.fileName),1,fp);
				fprintf(fp,"\n");
				fprintf(fp,"FILE PATH : ");
				fwrite(tmp->file.fullPath,strlen(tmp->file.fullPath),1,fp);
				fprintf(fp,"\n\n\n\n");
		}
	}

	fclose(fp);


	/* if no file match was found or file write gave error */
	if(count == 0){
		sprintf(outputStr,"%s %s","searchfile_SUCCESS","0");
		return outputStr;
	}
	else if( count>0 ){
		sprintf(outputStr,"%s %d","searchfile_SUCCESS",count);
		return outputStr;
	}
}

char* search_file(char *P1, char *P2){
	if(strlen(P2) == 0 || strlen(P1) ==0 ){
		sprintf(output_message,"%s %s","searchfile_FAILURE",ERR_VFS_SEARCHFILE_00);
		return output_message;
	}
	/*FILE *fp = fopen(P2, "rb");
	if(fp == NULL){
		sprintf(output_message,"%s %s","searchfile_FAILURE",ERR_VFS_SEARCHFILE_01);
		return output_message;	
	}
	*/
	if (h == NULL || l1 == NULL) {
		sprintf(output_message,"%s %s","searchfile_FAILURE",ERR_VFS_SEARCHFILE_02);	
		return output_message;
	}
		
	return htable_search(hashtable, P1, P2);
}
